package com.voice.core.connection.frame;

import com.voice.core.connection.Connection;

import java.nio.ByteBuffer;

public abstract class Frame {

    public byte[] payload;

    public byte flag;

    public int length;

    public byte type;

    public int streamId;

    public int position=0;

    public static int headerLength=9;

    private Runnable writeCallback;


    public int readHeader(byte[] bytes){
        return readHeader(bytes,bytes[0]&0xff<<16|bytes[1]&0xff<<8|bytes[2]&0xff);
    }

    public int readHeader(byte[] bytes,int length){
        this.length=length;
        payload=new byte[length+headerLength];
        type=bytes[3];
        flag=bytes[4];
        streamId=(bytes[5]&0x7f)<<24|bytes[6]&0xff<<16|bytes[7]&0xff<<8|bytes[8]&0xff;
        for(int i=0;i<bytes.length;i++){
            payload[position++]=bytes[i];
        }
        return bytes.length;
    }

    public int read(ByteBuffer buffer){
        int size=Math.min(buffer.remaining(),payload.length-position);
        for(int i=0;i<size;i++){
            payload[position++]=buffer.get();
        }
        return size;
    }

    public int write(ByteBuffer buffer){
        int size=Math.min(buffer.remaining(),payload.length-position);
        buffer.put(payload,position,size);
        position+=size;
        return size;
    }

    public boolean writeFinish(){
        boolean finish= position==payload.length;
        if(finish&&writeCallback!=null) writeCallback.run();
        return finish;
    }

    public boolean readFinish(){
        return position==payload.length;
    }

    public abstract byte[] getData();

    public abstract void onFinish(Connection connection);

    public void setWriteCallback(Runnable writeCallback){
        this.writeCallback=writeCallback;
    }

}
